/*
 *  Emotion Media Center
 *
 *  Copyright (C) 2009 Davide Andreoli <dave@gurumeditation.it>
 *
 *  License LGPL-2.1, see COPYING file at project folder.
 *
 */

#include "emc.h"
#include "emc_module.h"
#include "emc_input.h"
#include "emc_mainmenu.h"
#include "emc_browser_obj.h"
#include "emc_gui.h"
#include "emc_strbuf.h"
#include "emc_config.h"
#include "emc_games.h"

#define EMC_MODULE_NAME "games_sysgames"

#define LOCAL_DEBUG 1
#if LOCAL_DEBUG
#define D DBG
#else
#define D(...)
#endif

typedef struct _Game_Entry {
   const char *name;
   const char *icon;
   const char *exec;
} Game_Entry;

static Eina_List  *system_games = NULL;

/* Warning: this is NOT a proper implementation of the Icon Theme 
   Specification; it is hugely simplified to cover only our needs */

static char *
_check_icon(const char *icon, const char *dir, const char *ext)
{
   char tmp[PATH_MAX];
   char *format;

   if (ext)
      format = "%s/%s.%s";
   else
      format = "%s/%s";

   snprintf(tmp, sizeof (tmp), format, dir, icon, ext);

   if (!ecore_file_is_dir(tmp) && ecore_file_can_read(tmp))
      return strdup(tmp);
   else
      return NULL;
}

static char *
_check_icons(const char *icon, const char *dir)
{
   char *iconpath;

   if ((iconpath = _check_icon(icon, dir, NULL)))
      return iconpath;
   else if ((iconpath = _check_icon(icon, dir, "png")))
      return iconpath;
   else if ((iconpath = _check_icon(icon, dir, "xpm")))
      return iconpath;
   else if ((iconpath = _check_icon(icon, dir, "svg")))
      return iconpath;
   else
      return NULL;
}

static char *
_find_icon(const char *icon, const char *dir)
{
   char *iconpath;
   char tmp[PATH_MAX];

   if ((iconpath = _check_icons(icon, dir)))
      return iconpath;

   snprintf(tmp, sizeof (tmp), "%s/hicolor/128x128/apps", dir);
   if ((iconpath = _check_icons(icon, strdup(tmp))))
      return iconpath;

   snprintf(tmp, sizeof (tmp), "%s/hicolor/64x64/apps", dir);
   if ((iconpath = _check_icons(icon, strdup(tmp))))
      return iconpath;
       
   snprintf(tmp, sizeof (tmp), "%s/hicolor/48x48/apps", dir);
   if ((iconpath = _check_icons(icon, strdup(tmp))))
      return iconpath;

   snprintf(tmp, sizeof (tmp), "%s/hicolor/scalable/apps", dir);
   if ((iconpath = _check_icons(icon, strdup(tmp))))
      return iconpath;

   return NULL;
}

static Game_Entry *
_parse_desktop_game(const char *file)
{
   Game_Entry *game = NULL;
   const char *categories;
   Efreet_Ini *ini;

   ini = efreet_ini_new(file);

   efreet_ini_section_set(ini, "Desktop Entry");
   categories = efreet_ini_string_get(ini, "Categories");
   if (categories && strstr(categories, "Game"))
   {
      const char *tmpicon;
      const char *name = efreet_ini_string_get(ini, "Name");
      const char *icon = efreet_ini_string_get(ini, "Icon");
      const char *exec = efreet_ini_string_get(ini, "Exec");
        
      game = EMC_NEW(Game_Entry);
      game->name = eina_stringshare_add(name);
      game->exec = eina_stringshare_add(exec);

      if (!ecore_file_is_dir(icon) && ecore_file_can_read(icon))
          game->icon = eina_stringshare_add(icon);
      else if ((tmpicon = _find_icon(icon, "/usr/share/icons")))
          game->icon = tmpicon;
      else if ((tmpicon = _find_icon(icon, "/usr/share/pixmaps")))
          game->icon = tmpicon;
   }

   efreet_ini_free(ini);

   return game;
}

static void
_parse_directory(const char *dir_path)
{
   struct dirent *dp;
   DIR *dir;

   if (!(dir = opendir(dir_path))) return;

   while ((dp = readdir(dir)))
   {
      Game_Entry *game;
      char buf[PATH_MAX];

      if (!eina_str_has_extension(dp->d_name, "desktop")) continue;
      snprintf(buf, sizeof(buf), "%s/%s", dir_path, dp->d_name);
      
      if ((game = _parse_desktop_game(buf)))
      {
         system_games = eina_list_append(system_games, game);
      }
   }
   closedir(dir);
}

static void
_sysgames_build_list(void)
{
   char gamesdir[4096];

   D(" ");

   sprintf(gamesdir, "%s/games", efreet_config_home_get());
   _parse_directory(gamesdir);
   _parse_directory("/usr/share/applications");
}

/******************************************************************************/
/*                     GUI (browser object)                                   */
/******************************************************************************/

static void
_browser_selected_cb(void *data, Evas_Object *obj, void *event_info)
{
   Emc_Browser_Item *item = event_info;

   emc_games_exec(item->uri, _("<c>System Games</c><br>Game running..."));

}

static void
_sysgames_show(void *data)
{
   Evas_Object *brow;
   Eina_List *list = NULL, *l;
   Emc_Browser_Item *item;
   Game_Entry *game;

   if (!system_games)
   {
      // build game list //TODO show a dialog while doing this
      _sysgames_build_list();
   }

   brow = emc_browser_obj_add(evas_object_evas_get(emc->layout));
   evas_object_smart_callback_add(brow, "selected", _browser_selected_cb, NULL);

   EINA_LIST_FOREACH(system_games, l, game)
   {
      item = emc_browser_item_new(game->exec, game->name, game->icon, EINA_TRUE);
      list = eina_list_append(list, item);
   }

   emc_browser_obj_push(brow, list, EINA_FALSE);
   emc_gui_content_show(brow);
}

/******************************************************************************/
/*                     Module interface                                       */
/******************************************************************************/

Eina_Bool
module_init(Emc_Module *em)
{
   Evas_Object *ic;
   
   D(" ");

   // add mainmenu item
   ic = elm_icon_add(emc->win);
   elm_icon_file_set(ic, emc->theme_file, "icon/games");
   emc_mainmenu_item_append("games_sysgames", "System", ic, "games", 5,
                            _sysgames_show, NULL);

   return EINA_TRUE;
}

Eina_Bool
module_shutdown(Emc_Module *em)
{
   Game_Entry *game;

   //TODO if a game is running ??

   EINA_LIST_FREE(system_games, game)
   {
      EMC_STRINGSHARE_DEL(game->name);
      EMC_STRINGSHARE_DEL(game->icon);
      EMC_STRINGSHARE_DEL(game->exec);
      EMC_FREE(game);
   }
   emc_mainmenu_item_del("games_sysgames");
   return EINA_TRUE;
}

Emc_Module_Api module_api =
{
   EMC_MODULE_API_VERSION,
   EMC_MODULE_NAME,
   "System Games",
   NULL,
   "Module to play linux installed games",
   "bla bla bla<br><b>bla bla bla</b><br><br>bla.",
   {
      module_init,
      module_shutdown
   }
};
